package com.zxjbyte.yiyi.framework.common.annotation.validated;

import cn.hutool.core.util.ArrayUtil;
import com.zxjbyte.yiyi.framework.common.constant.StringPool;
import com.zxjbyte.yiyi.framework.common.core.ObjectArrayFactory;
import com.zxjbyte.yiyi.framework.common.annotation.InEnumValue;

import javax.validation.ConstraintValidator;
import javax.validation.ConstraintValidatorContext;
import java.util.Objects;

/**
 * 是否属于枚举值范围校验
 * @Author zhangxingjia
 * @Date 2023/3/15 17:35
 * @Version: 1.0
 */

public class InEnumValueValidator implements ConstraintValidator<InEnumValue, Object> {

    private boolean ignoreCase;
    private Object[] ObjectArr;

    @Override
    public void initialize(InEnumValue constraintAnnotation) {
        ignoreCase = constraintAnnotation.ignoreCase();
        ObjectArrayFactory[] enumConstants = constraintAnnotation.enumClass().getEnumConstants();
        if (enumConstants.length == 0) {
            this.ObjectArr = ArrayUtil.newArray(0);
        } else {
            this.ObjectArr = enumConstants[0].array();
        }
    }

    @Override
    public boolean isValid(Object value, ConstraintValidatorContext context) {
        // 为空不校验，即认为通过
        if (Objects.isNull(value)) {
            return true;
        }
        // 校验通过
        if (value instanceof String && ObjectArr instanceof String[]) {
            String strValue = (String) value;
            if(ignoreCase ? ArrayUtil.containsIgnoreCase((String[])ObjectArr, strValue)
                    : ArrayUtil.contains((String[])ObjectArr, strValue)){
                return true;
            }
        } else if(ArrayUtil.contains(ObjectArr, value)) {
            return true;
        }
        // 校验不通过，自定义提示语句（因为，注解上的 value 是枚举类，无法获得枚举类的实际值）
        context.disableDefaultConstraintViolation(); // 禁用默认的 message 的值
        context.buildConstraintViolationWithTemplate(String.format(context.getDefaultConstraintMessageTemplate(),
                ArrayUtil.join(ObjectArr, StringPool.COMMA))).addConstraintViolation(); // 重新添加错误提示语句
        return false;
    }
}
